package com.browsesoft.htmlcomponent;

import java.lang.reflect.Constructor;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.aote.util.ComponentHelper;
import com.browsesoft.SequenceFind;

/**
 * html基本组件
 */
public class HTMLBasicComponent {
	/**
	 * 子组件列表
	 */
	protected LinkedList components = new LinkedList();

	/**
	 * 页面
	 */
	protected HTMLBasicComponent parent = null;

	/**
	 * HTML组件对应的数据模型
	 */
	protected HTMLBasicModel model = null;

	/**
	 * 组件所对应的元素
	 */
	protected Element element = null;

	/**
	 * 组件名字
	 */
	protected String name = "";

	private HttpServletRequest request;

	/**
	 * 构造器
	 * 
	 * @param parent
	 *            组件的父组件
	 */
	public HTMLBasicComponent(HTMLBasicComponent parent) throws Exception {
		// 设置组件的名字
		name = Integer.toString(SequenceFind.getID());
		// 设置组件的父组件
		this.parent = parent;
	}

	/**
	 * 初始化时创建子组件并设置初始化参数
	 */
	public void init(HttpServletRequest request, Element e) throws Exception {
		// 得到组件element
		element = e;
		// 创建子组件
		createComponents(request, e);
	}

	/**
	 * 产生子组件并设置组件的model
	 * 
	 * @param e
	 *            元素
	 */
	private void createComponents(HttpServletRequest request, Element e)
			throws Exception {
		// 取得元素子结点列表
		NodeList list = e.getChildNodes();
		// 找出有component属性的子结点元素
		for (int i = 0; i < list.getLength(); i++) {
			Node node = list.item(i);
			// 如果子结点是元素
			if (node instanceof Element) {
				// 取得component属性值
				String value = ((Element) node).getAttribute("component");
				// 如果有值
				if (value.length() > 0) {
					// 取得以component属性值为类名的类的构造器
					Class[] c = { Class
							.forName("com.browsesoft.htmlcomponent.HTMLBasicComponent") };
					Constructor constr = Class.forName(value).getConstructor(c);
					// 以此构造器新建组件
					HTMLBasicComponent component = (HTMLBasicComponent) constr
							.newInstance(new Object[] { this });
					// 设置组件元素
					component.setElement((Element) node);

					// 取得节点元素的model属性值
					String mod = ((Element) node).getAttribute("model");
					// 如果有model属性值
					if (!mod.equals("")) {
						// 新建model
						HTMLBasicModel model = (HTMLBasicModel) Class.forName(
								mod).newInstance();
						// 设置组件的model
						component.setModel(model);
						// 初始化Model
						model.init(request);
					}
					// 添加子组件
					components.add(component);
					// 初始化组件
					component.init(request, (Element) node);
				} else {
					// 递归产生子组件
					createComponents(request, (Element) node);
				}
			}
		}

	}

	/**
	 * 设置HTML组件的数据存储Model
	 * 
	 * @param model
	 *            数据存储Model
	 */
	public void setModel(HTMLBasicModel model) throws Exception {
		// 设置模型
		this.model = model;
		// 模型设置组件
		model.setComponent(this);
	}

	/**
	 * 设置子组件元素
	 * 
	 */
	public void setElement(Element e) throws Exception {
		this.element = e;
	}

	/**
	 * 得到组件元素
	 */
	public Element getElement() {
		// 返回本组件元素
		return this.element;
	}

	/**
	 * 取得组件名字
	 */
	public String getName() {
		// 返回本组件名字
		return this.name;
	}

	/**
	 * 得到页面
	 */
	public HTMLPage getPage() {
		HTMLBasicComponent p = this;
		while (!(p instanceof HTMLPage)) {
			p = p.parent;
		}
		return (HTMLPage) p;
	}

	/**
	 * 处理更新过程
	 */
	protected void update() throws Exception {
		if (model != null) {
			model.updatePageElement(this);
		}
		// 让子组件继续调用自已updateElement()
		for (int i = 0; i < components.size(); i++) {
			((HTMLBasicComponent) components.get(i)).update();
		}
		ComponentHelper.disposeHidden(this.request, this);
		this.updateElement();
	}

	/**
	 * 根据Model的内容更新需要处理的元素内容，在产生页面时要调用
	 * 如果需要Model处理的元素，则在该方法中调用HTMLBasicModel.updateElement()
	 */
	protected void updateElement() throws Exception {
	}

	/**
	 * 处理用户请求，将需要Model处理的内容提交给Model
	 * 
	 * @param request
	 *            客户端请求
	 */
	protected void service(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		this.request = request;
	}

	/**
	 * 调度过程
	 * 
	 * @throws Exception
	 * 
	 */
	public void dispatch(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (this instanceof ChildPrecedence) {
			childDispose(request, response);
			selfDispose(request, response);
		} else {
			selfDispose(request, response);
			childDispose(request, response);
		}
	}

	protected void childDispose(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		// 每一个组件自己去处理页面请求
		for (int i = 0; i < components.size(); i++) {
			HTMLBasicComponent component = (HTMLBasicComponent) components
					.get(i);
			component.dispatch(request, response);
		}
	}

	protected void selfDispose(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		this.replaceSelfParameter(request, this);
		// 先让自己的模型处理，然后再让子处理
		if (model != null) {
			model.service(request, response);
		}
		this.service(request, response);
	}

	/**
	 * 替换自己的参数
	 */
	protected void replaceSelfParameter(HttpServletRequest request,
			HTMLBasicComponent component) {
	}

	/**
	 * 根据ID号得到组件
	 */
	public static HTMLBasicComponent getComponentByID(
			HttpServletRequest request, String ID) {
		// 得到session
		HttpSession session = request.getSession();
		// 从session中得到所有对象名
		Enumeration en = session.getAttributeNames();
		// 对于每一个对象名
		while (en.hasMoreElements()) {
			// 得到对应的对象
			String name = (String) en.nextElement();
			Object obj = session.getAttribute(name);
			// 如果该对象是页面
			if (obj instanceof HTMLPage) {
				// 从页面中得到组件
				HTMLBasicComponent comp = ((HTMLBasicComponent) obj)
						.getComponentByID(ID);
				// 如果得到了
				if (comp != null) {
					return comp;
				}
			}
		}
		return null;
	}

	/**
	 * 根据给定ID得到子组件，包括自己，包括所有后代
	 */
	protected HTMLBasicComponent getComponentByID(String ID) {
		// 如果自己ID号与给定的相同
		if (this.getName().equals(ID)) {
			// 返回自己
			return this;
		}
		// 对于本组件每一个直接子
		Iterator iter = components.iterator();
		while (iter.hasNext()) {
			HTMLBasicComponent item = (HTMLBasicComponent) iter.next();
			// 让子找
			HTMLBasicComponent result = item.getComponentByID(ID);
			// 如果找到了
			if (result != null) {
				return result;
			}
		}
		return null;
	}

	/**
	 * 得到组建所对应的Model
	 * 
	 * @return Model
	 */
	public HTMLBasicModel getModel() {
		return this.model;
	}

	/**
	 * 返回当前组建的父组件
	 * 
	 * @return 父组件
	 */
	public HTMLBasicComponent getParent() {
		return this.parent;
	}

	/**
	 * 返回所有子组件
	 * 
	 * @return 子组件列表
	 */
	public Iterator getChildrenComponents() {
		return this.components.iterator();
	}

	/**
	 * 从请求中取值，并将结果按相应字符集转换
	 * 
	 * @param request
	 *            请求
	 * @param name
	 *            要取得参数名
	 * @return 取得的结果
	 */
	public static String getValue(HttpServletRequest request, String name) {
		try {
			String result = request.getParameter(name);
			// 如果值不为空
			return result;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}